/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Assert; import jxl.common.Logger; import jxl.CellType; import jxl.WorkbookSettings; import jxl.biff.DoubleHelper; import jxl.biff.FormattingRecords; import jxl.biff.IntegerHelper; import jxl.biff.WorkbookMethods; import jxl.biff.formula.ExternalSheet; /** * A formula's last calculated value */ class FormulaRecord extends CellValue { /** * The logger */ private static Logger logger = Logger.getLogger(FormulaRecord.class); /** * The "real" formula record - will be either a string a or a number */ private CellValue formula; /** * Flag to indicate whether this is a shared formula */ private boolean shared; /** * Static class for a dummy override, indicating that the formula * passed in is not a shared formula */ private static class IgnoreSharedFormula {}; public static final IgnoreSharedFormula ignoreSharedFormula = new IgnoreSharedFormula(); /** * Constructs this object from the raw data. Creates either a * NumberFormulaRecord or a StringFormulaRecord depending on whether * this formula represents a numerical calculation or not * * @param t the raw data * @param excelFile the excel file * @param fr the formatting records * @param es the workbook, which contains the external sheet references * @param nt the name table * @param si the sheet * @param ws the workbook settings */ public FormulaRecord(Record t, File excelFile, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si, WorkbookSettings ws) { super(t, fr, si); byte[] data = getRecord().getData(); shared = false; // Check to see if this forms part of a shared formula int grbit = IntegerHelper.getInt(data[14], data[15]); if ((grbit & 0x08) != 0) { shared = true; if (data[6] == 0 && data[12] == -1 && data[13] == -1) { // It is a shared string formula formula = new SharedStringFormulaRecord (t, excelFile, fr, es, nt, si, ws); } else if (data[6] == 3 && data[12] == -1 && data[13] == -1) { // We have a string which evaluates to null formula = new SharedStringFormulaRecord (t, excelFile, fr, es, nt, si, SharedStringFormulaRecord.EMPTY_STRING); } else if (data[6] == 2 && data[12] == -1 && data[13] == -1) { // The cell is in error int errorCode = data[8]; formula = new SharedErrorFormulaRecord(t, excelFile, errorCode, fr, es, nt, si); } else if (data[6] == 1 && data[12] == -1 && data[13] == -1) { boolean value = data[8] == 1 ? true : false; formula = new SharedBooleanFormulaRecord (t, excelFile, value, fr, es, nt, si); } else { // It is a numerical formula double value = DoubleHelper.getIEEEDouble(data, 6); SharedNumberFormulaRecord snfr = new SharedNumberFormulaRecord (t, excelFile, value, fr, es, nt, si); snfr.setNumberFormat(fr.getNumberFormat(getXFIndex())); formula = snfr; } return; } // microsoft and their goddam magic values determine whether this // is a string or a number value if (data[6] == 0 && data[12] == -1 && data[13] == -1) { // we have a string formula = new StringFormulaRecord(t, excelFile, fr, es, nt, si, ws); } else if (data[6] == 1 && data[12] == -1 && data[13] == -1) { // We have a boolean formula // multiple values. Thanks to Frank for spotting this formula = new BooleanFormulaRecord(t, fr, es, nt, si); } else if (data[6] == 2 && data[12] == -1 && data[13] == -1) { // The cell is in error formula = new ErrorFormulaRecord(t, fr, es, nt, si); } else if (data[6] == 3 && data[12] == -1 && data[13] == -1) { // we have a string which evaluates to null formula = new StringFormulaRecord(t, fr, es, nt, si); } else { // it is most assuredly a number formula = new NumberFormulaRecord(t, fr, es, nt, si); } } /** * Constructs this object from the raw data. Creates either a * NumberFormulaRecord or a StringFormulaRecord depending on whether * this formula represents a numerical calculation or not * * @param t the raw data * @param excelFile the excel file * @param fr the formatting records * @param es the workbook, which contains the external sheet references * @param nt the name table * @param i a dummy override to indicate that we don't want to do * any shared formula processing * @param si the sheet impl * @param ws the workbook settings */ public FormulaRecord(Record t, File excelFile, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, IgnoreSharedFormula i, SheetImpl si, WorkbookSettings ws) { super(t, fr, si); byte[] data = getRecord().getData(); shared = false; // microsoft and their magic values determine whether this // is a string or a number value if (data[6] == 0 && data[12] == -1 && data[13] == -1) { // we have a string formula = new StringFormulaRecord(t, excelFile, fr, es, nt, si, ws); } else if (data[6] == 1 && data[12] == -1 && data[13] == -1) { // We have a boolean formula // multiple values. Thanks to Frank for spotting this formula = new BooleanFormulaRecord(t, fr, es, nt, si); } else if (data[6] == 2 && data[12] == -1 && data[13] == -1) { // The cell is in error formula = new ErrorFormulaRecord(t, fr, es, nt, si); } else { // it is most assuredly a number formula = new NumberFormulaRecord(t, fr, es, nt, si); } } /** * Returns the numerical value as a string * * @return The numerical value of the formula as a string */ public String getContents() { Assert.verify(false); return ""; } /** * Returns the cell type * * @return The cell type */ public CellType getType() { Assert.verify(false); return CellType.EMPTY; } /** * Gets the "real" formula * * @return the cell value */ final CellValue getFormula() { return formula; } /** * Interrogates this formula to determine if it forms part of a shared * formula * * @return TRUE if this is shared formula, FALSE otherwise */ final boolean isShared() { return shared; } }